package com.nyist.springcloud.controller;

import com.nyist.springcloud.ResultVO;
import com.nyist.springcloud.entities.Payment;
import com.nyist.springcloud.lb.MyWriteRule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.net.URI;
import java.util.List;

/**
 * @author yangxiaogen
 * @date 2021/1/23 17:02
 */
@RestController
@RequestMapping("/consumer")
@Slf4j
public class OrderController {

    //public static final String PAYMENT_URL = "http://127.0.0.1:8001";
    public static final String PAYMENT_URL = "http://PAYMENT-SERVICE";

    @Resource
    private MyWriteRule loadBalancer;
    @Resource
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @PostMapping("/pay/create")
    public ResultVO<Payment> createPay(@RequestBody Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL + "/pay/create", payment, ResultVO.class);
    }

    @PostMapping("/pay/get")
    public ResultVO<Payment> getPay(@RequestBody Payment payment) {
        ResultVO<Payment> resultVO = restTemplate.postForObject(PAYMENT_URL + "/pay/get", payment, ResultVO.class);
        return resultVO;
    }

    /**
     *
     * 自己手写负载均衡算法, 需要注意的点
     * 1. 去掉RestTemplate 上的 @LoadBalanced 注解, 改为使用自己的策略
     * 2. 去掉启动类上的 @RibbonClient注解
     * 3. 需要自己去实现获取当前服务器的方法, 并且计算使用那个提供服务的服务器, 为消费者使用
     * 4. 在定义的接口实现类上加入 @Component 注解将类注入到容器中
     *
     * 5. 对于 @Component 注解的解读 , 将普通的类注入到容器中,
     *    供spring管理,在我们使用的时候就可以直接通过 @Resource 或者 @Autowired 引入
     *    与 @Configuration 的区别在于, Configuration在被多次调用的时候使用的是同一个对象
     *    而 @Component 在多次被调用的时候, 使用的是 不同的对象
     *
     *
     * @author yangxiaogen 
     * @date 2021/1/29 15:35
     * @param payment
     * @return com.nyist.springcloud.ResultVO<com.nyist.springcloud.entities.Payment>
     */

    @PostMapping(value = "/pay/lb")
    public ResultVO<Payment> getPaymentLb(@RequestBody Payment payment) {
        // 获取当前 , 提供服务的所有的服务器
        List<ServiceInstance> instances = discoveryClient.getInstances("PAYMENT-SERVICE");

        if (instances == null || instances.size() <= 0) {
            return null;
        }
        // 获取当前服务器的实例
        ServiceInstance serviceInstance = loadBalancer.instances(instances);
        // 找到对应的地址
        URI uri = serviceInstance.getUri();
        // 发起请求
        return restTemplate.postForObject(uri + "/pay/lb", payment, ResultVO.class);
    }

}
